package com.mall.controller;

import com.mall.common.constants.Constants;
import com.mall.common.resp.ResponseResult;
import com.mall.common.utils.Captcha;
import com.mall.common.utils.FileUtils;
import com.mall.entity.User;
import com.mall.service.OrderService;
import com.mall.service.PvService;
import com.mall.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author xyl
 * @create 2020-12-07 15:20
 * @desc 测试接口
 **/
@Api(tags = "通用请求接口 , 注册 , 获取验证码等")
@Controller
@RequestMapping("mall")
public class CommonController {

    @Autowired
    private Captcha captcha;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserService userService;
    @Autowired
    private PvService pvService;
    @Autowired
    private OrderService orderService;

    @ApiOperation("注册接口")
    @PostMapping("register")
    @ResponseBody
    public ResponseResult register(@Validated @RequestBody User user, HttpServletRequest request) {
        User dbUser = userService.getUserByEmail(user.getEmail());
        if (!ObjectUtils.isEmpty(dbUser)) {
            return ResponseResult.error(user.getEmail() + "已存在 , 请进行登录!");
        }
        //验证邮箱验证码
        String register_code = (String) redisTemplate.opsForValue().get(Constants.REGISTER_MAIL_CAPTCHA_PREFIX + request.getSession().getId());
        System.out.println(request.getSession().getId());
        if (!redisTemplate.hasKey(Constants.REGISTER_MAIL_CAPTCHA_PREFIX + request.getSession().getId())) {
            return ResponseResult.error("邮箱验证码已过期!");
        }
        if (!user.getMailCode().equalsIgnoreCase(register_code)) {
            return ResponseResult.error("邮箱验证码有误!");
        }
        //设置为普通用户
        user.setRoleKey(Constants.ROLE_USER);
        return ResponseResult.toResponse(userService.addUser(user));
    }

    @ApiOperation("获取验证码接口")
    @GetMapping("captcha")
    @ResponseBody
    public ResponseResult getCaptcha(HttpServletRequest request) {
        String verifyCode = captcha.generateVerifyCode(4);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            captcha.outputImage(100, 40, outputStream, verifyCode);
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        String imageStr = encoder.encode(outputStream.toByteArray());
        System.out.println("验证码:" + verifyCode);
        redisTemplate.opsForValue().set(Constants.REDIS_KEY_CAPTCHA_PREFIX + request.getSession().getId(), verifyCode, Constants.CAPTCHA_EXPIRE_TIME, TimeUnit.MINUTES);
        return ResponseResult.success(imageStr);
    }

    @ApiIgnore
    @GetMapping("/login")
    public String login() {
        return "login";
    }
//    @PreAuthorize("hasRole('USER')")
//    @PreAuthorize("hasRole('ADMIN')")

    @ApiOperation("发送邮箱验证码 , 注册时进行发送")
    @ResponseBody
    @PostMapping("/send/mail")
    public ResponseResult sendMail(@RequestParam String mail, HttpServletRequest request) {
        if (StringUtils.isEmpty(mail)) {
            return ResponseResult.error("mail不能为null");
        } else {
            userService.sendMail(mail, Constants.REGISTER_MAIL_CAPTCHA_PREFIX + request.getSession().getId());
        }
        //todo 默认返回为成功
        return ResponseResult.success();
    }

    @GetMapping("/get/session")
    @ResponseBody
    public ResponseResult getSessionId(HttpServletRequest request) {
        return ResponseResult.success(request.getSession().getId());
    }

    @ApiOperation("通用上传图片接口 ，上传图片为base64格式")
    @PostMapping("/upload/image")
    @ResponseBody
    public ResponseResult uploadImage(@RequestParam String base64Image) {
        String s = FileUtils.Base64ToImage(Constants.NATIVE_IMAGE_PATH, base64Image);
        if (StringUtils.isEmpty(s)) {
            return ResponseResult.error("格式有误！");
        }
        return ResponseResult.success(Constants.VIRTUAL_IMAGE_PATH + s);
    }

    @ApiOperation("1.重置密码时,验证当前用户邮箱")
    @PostMapping("/verify/mail")
    @ResponseBody
    public ResponseResult verifyMail(@RequestParam String mail, HttpServletRequest request) {
        if (userService.verifyMail(mail, request)) {
            redisTemplate.opsForValue().set(Constants.MAIL_KEY_CAPTCHA_PREFIX + request.getSession().getId(), mail, Constants.REGISTER_MAIL_EXPIRE_TIME, TimeUnit.MINUTES);
            userService.sendMail(mail, Constants.VERIFY_MAIL_KEY_CAPTCHA_PREFIX + request.getSession().getId());
            return ResponseResult.success("邮箱验证已发送!");
        } else {
            return ResponseResult.error("邮箱不存在!");
        }
    }

    @ApiOperation("2.重置密码时,验证邮箱码")
    @PostMapping("/verify/mailCode")
    @ResponseBody
    public ResponseResult verifyMailCode(@RequestParam String mailCode, HttpServletRequest request) {
        String s = (String) redisTemplate.opsForValue().get(Constants.VERIFY_MAIL_KEY_CAPTCHA_PREFIX + request.getSession().getId());
        if (mailCode.equalsIgnoreCase(s)) {
            return ResponseResult.success("验证成功!");
        } else {
            return ResponseResult.error("邮箱码不匹配!");
        }
    }

    @ApiOperation("3.重置密码")
    @PostMapping("/reset/password")
    @ResponseBody
    public ResponseResult resetPassword(@RequestParam String password, HttpServletRequest request) {
        String s = (String) redisTemplate.opsForValue().get(Constants.MAIL_KEY_CAPTCHA_PREFIX + request.getSession().getId());
        if (StringUtils.isEmpty(s)) {
            return ResponseResult.error("时间过长已失效");
        } else {
            return ResponseResult.toResponse(userService.modifyUserPasswordByMail(s, password));
        }
    }

    @ApiOperation("+访问量")
    @GetMapping("pv")
    @ResponseBody
    public ResponseResult pv(HttpServletRequest request){
        return ResponseResult.toResponse(pvService.addPv(getIpAddress(request)));
    }


    @ApiOperation("管理员,  获取访问量")
    @GetMapping("/get/pv")
    @PreAuthorize("hasRole('ADMIN') or hasRole('COMMON_ADMIN')")
    public ResponseResult<Map> getViewInfo(){
        Map<String,Integer> map = new HashMap<>(2);
        map.put("todayPv",pvService.getTodayPv());
        map.put("totalPv",pvService.getTotalPv());
        return new ResponseResult<>(map);
    }

    private static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
                //根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ip = inet.getHostAddress();
            }
        }
        return ip;
    }

}